#include<cstdio>
#include<vector>
#include<semaphore.h>
#include<pthread.h>

#define MAX_QUEUE 5
class RingQueue{
  private:
    int _capacity;//队列容量
    int _read;//读指针
    int _write;//写指针
    std::vector<int> _array;
    sem_t _sem_data;//数据节点计数
    sem_t _sem_idle;//空闲节点计数
    sem_t _sem_lock;//用于实现互斥
  public:
    RingQueue(int max = MAX_QUEUE)
      :_capacity(max)
      ,_read(0)
      ,_write(0)
      ,_array(max)
    {     //sem_init(信号量，share标志，初值)
       sem_init(&_sem_data, 0, 0);//share标志为0是线程的同步互斥
       sem_init(&_sem_idle, 0, max);
       sem_init(&_sem_lock, 0, 1);
    }

    ~RingQueue() {
      sem_destroy(&_sem_data);
      sem_destroy(&_sem_idle);
      sem_destroy(&_sem_lock);
    }

    bool Push(const int& data){
      sem_wait(&_sem_idle);//空闲节点-1
      sem_wait(&_sem_lock);//加锁
      _array[_write] = data;
      _write = (_write + 1)% _capacity;
      sem_post(&_sem_lock);//解锁
      sem_post(&_sem_data);//数据节点+1
      return true;
    }
    
     bool Pop(int *buf) {
       sem_wait(&_sem_data);// 数据节点-1
       sem_wait(&_sem_lock);//加锁
       *buf = _array[_read];
       _read = (_read + 1) % _capacity;
       sem_post(&_sem_lock);//解锁
       sem_post(&_sem_idle);//空闲节点+1
       return true;
    }
};

void *productor(void *arg)
{
    RingQueue *q = (RingQueue*)arg;
    int data = 0;
    while(1) {
        q->Push(data);
        printf("push data: %d++++++\n", data++);
    }
    return NULL;
}
void *customer(void *arg)
{
    RingQueue *q = (RingQueue*)arg;
    while(1) {
        int data = 0;
        q->Pop(&data);
        printf("pop data: %d------\n", data);
    }
    return NULL;
}

int main()
{
    RingQueue q;
    int ret;
    pthread_t ptid[4], ctid[4];
    for (int i = 0; i < 4; i++) {
        ret = pthread_create(&ptid[i], NULL, productor, &q);
        if (ret != 0) {
            printf("thread create error\n");
            return -1;
        }
        ret = pthread_create(&ctid[i], NULL, customer, &q);
        if (ret != 0) {
            printf("thread create error\n");
            return -1;
        }
    }
    for (int i = 0; i < 4; i++) {
        pthread_join(ptid[i], NULL);
        pthread_join(ctid[i], NULL);
    }
    return 0;
}


